package org.sky.util.file;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author weifx
 * @Title: ZipUtils
 * @ProjectName springboot-platform
 * @Description: TODO{Zip文件压缩工具类}
 * @date 2019/3/18 9:42
 * @Version 1.0
 */
public class ZipUtils {
    /**
     * 压缩
     * @param zipFileName
     *            压缩产生的zip包文件名--带路径,如果为null或空则默认按文件名生产压缩文件名
     * @param relativePath
     *            相对路径，默认为空
     * @param directory
     *            文件或目录的绝对路径
     * @throws FileNotFoundException
     * @throws IOException
     * @author
     * @date 2008-8-26
     */
    public static void zip(String zipFileName, String relativePath,
                           String directory) throws FileNotFoundException, IOException {
        String fileName = zipFileName;
        if (fileName == null || fileName.trim().equals("")) {
            File temp = new File(directory);
            if (temp.isDirectory()) {
                fileName = directory + ".zip";
            } else {
                if (directory.indexOf(".") > 0) {
                    fileName = directory.substring(0,
                            directory.lastIndexOf("."))
                            + "zip";
                } else {
                    fileName = directory + ".zip";
                }
            }
        }
        ZipOutputStream zos = new ZipOutputStream(
                new FileOutputStream(fileName));
        try {
            zip(zos, relativePath, directory);
        } catch (IOException ex) {
            throw ex;
        } finally {
            if (null != zos) {
                zos.close();
            }
        }
    }

    /**
     * 压缩
     * @param zos
     *            压缩输出流
     * @param relativePath
     *            相对路径
     * @param absolutPath
     *            文件或文件夹绝对路径
     * @throws IOException
     * @author
     * @date 2008-8-26
     */
    private static void zip(ZipOutputStream zos, String relativePath,
                            String absolutPath) throws IOException {
        File file = new File(absolutPath);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                File tempFile = files[i];
                if (tempFile.isDirectory()) {
                    String newRelativePath = relativePath + tempFile.getName()
                            + File.separator;
                    createZipNode(zos, newRelativePath);
                    zip(zos, newRelativePath, tempFile.getPath());
                } else {
                    zipFile(zos, tempFile, relativePath);
                }
            }
        } else {
            zipFile(zos, file, relativePath);
        }
    }

    /**
     * 压缩文件
     * @param zos
     *            压缩输出流
     * @param file
     *            文件对象
     * @param relativePath
     *            相对路径
     * @throws IOException
     * @author
     * @date 2008-8-26
     */
    private static void zipFile(ZipOutputStream zos, File file,
                                String relativePath) throws IOException {
        ZipEntry entry = new ZipEntry(relativePath + file.getName());
        zos.putNextEntry(entry);
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            int BUFFERSIZE = 2 << 10;
            int length = 0;
            byte[] buffer = new byte[BUFFERSIZE];
            while ((length = is.read(buffer, 0, BUFFERSIZE)) >= 0) {
                zos.write(buffer, 0, length);
            }
            zos.flush();
            zos.closeEntry();
        } catch (IOException ex) {
            throw ex;
        } finally {
            if (null != is) {
                is.close();
            }
        }
    }

    /**
     * 创建目录
     * @param zos
     *            zip输出流
     * @param relativePath
     *            相对路径
     * @throws IOException
     * @author
     * @date 2008-8-26
     */
    private static void createZipNode(ZipOutputStream zos, String relativePath)
            throws IOException {
        ZipEntry zipEntry = new ZipEntry(relativePath);
        zos.putNextEntry(zipEntry);
        zos.closeEntry();
    }
}
